package cn.dengta.webapp.user.entity;

import java.util.Arrays;
import java.util.Date;
import javax.annotation.Nullable;

import cn.dengta.common.model.*;
import cn.dengta.common.util.Common;
import cn.dengta.webapp.base.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import me.codeplayer.util.X;

/**
 * 关注
 *
 * @author lgy
 * @since 2022-03-07
 */
@Setter
@Getter
@Accessors(chain = true)
@TableName("dt_relation")
public class Relation extends BaseEntity {

	public static final String FOLLOWED_UNREAD_COUNT_KEY = "followedUnreadCount";
	public static final String FRIEND_COUNT_KEY = "friendCount";

	/** 用户ID */
	private Long userId;
	/** 关注状态 */
	private Integer status;
	/** 被关注状态 */
	private Integer toStatus;
	/** 被关注ID */
	private Long toUserId;
	/** 添加时间 */
	private Date addTime;
	protected State state;

	/** 自己的关注数 */
	private transient Integer follow;
	/** 好友数 */
	private transient Integer friend;

	public static boolean isFollow(Integer status) {
		return RelationStatus.BIND.eq(status);
	}

	public static boolean isBlock(Integer status) {
		return RelationStatus.BLOCK.eq(status);
	}

	public static boolean isToBlock(Integer status) {
		return RelationStatus.TO_BLOCK.eq(status);
	}

	public String redisMember() {
		return Common.sortKey(userId, toUserId, Common.LINE_SEP);
	}

	@Override
	public void setId(Long id) {
		this.id = id;
	}

	public void exchangeStatus(Relation followed, boolean addOrCancel, boolean isBlock) {
		final Integer status = RelationStatus.convert(addOrCancel, isBlock, true).value;
		final Integer toStatus = isBlock ? RelationStatus.convert(addOrCancel, true, false).value
				: X.expectNotNull(followed.getStatus(), RelationStatus.convert(!addOrCancel, false, false).value);
		this.setStatus(status).setToStatus(toStatus);
		followed.setStatus(toStatus).setToStatus(status);
	}

	/** 主动关注 */
	public boolean isFollow() {
		return RelationStatus.BIND.eq(status);
	}

	/** 主动关注 */
	public boolean isFriend() {
		return isFollow() && RelationStatus.BIND.eq(toStatus);
	}

	/** 拉黑 */
	public boolean isBlock() {
		return Arrays.stream(RelationStatus.BLOCK_CACHE).anyMatch(b -> b == RelationStatus.of(status));
	}

	@Getter
	public enum RelationStatus implements ValueProxyImpl<RelationStatus, Integer> {

		/** 拉黑 */
		TO_BLOCK(-2, "被拉黑", false),
		/** 拉黑 */
		BLOCK(-1, "拉黑", false),
		/** 取消喜欢 */
		WAIT_BIND(0, "待喜欢", true),
		/** 喜欢 */
		BIND(1, "喜欢", true),
		//
		;
		@EnumValue
		public final Integer value;
		public final boolean canFollow;
		final ValueProxy<RelationStatus, Integer> proxy;

		// 构造函数，枚举类型只能为私有
		RelationStatus(Integer value, String label, boolean canFollow) {
			this.value = value;
			this.canFollow = canFollow;
			this.proxy = new ValueProxy<>(this, value, label);
		}

		public static final RelationStatus[] CACHE = values();

		public static final RelationStatus[] BLOCK_CACHE = { RelationStatus.BLOCK, RelationStatus.TO_BLOCK };

		public static RelationStatus of(@Nullable Integer value) {
			return Common.getEnum(CACHE, RelationStatus::getValue, value);
		}

		public static RelationStatus convert(boolean addOrCancel, boolean isBlock, boolean fromOrTo) {
			return addOrCancel ? (isBlock ? (fromOrTo ? RelationStatus.BLOCK : RelationStatus.TO_BLOCK) : RelationStatus.BIND) : RelationStatus.WAIT_BIND;
		}

	}

	public static final String USER_ID = "user_id";
	public static final String TO_USER_ID = "to_user_id";
	public static final String TO_STATUS = "to_status";
	public static final String STATUS = "status";
	public static final String STATE = "state";
	public static final String ADD_TIME = "add_time";

}
